package com.ilarele.shopping.server.tags;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;

import com.ilarele.shopping.Product;
import com.ilarele.shopping.server.MysqlBasicOps;

public class TagsRecommendation {
	private MysqlBasicOps sqlOps;
	// id, users
	private HashMap<String, TagInfo> tags = new HashMap<String, TagInfo>();

	public TagsRecommendation(MysqlBasicOps sqlOps) {
		this.sqlOps = sqlOps;

		// for each tag
		ResultSet rs = sqlOps.getTagsRS();
		try {
			// for each tag from tags_preferences table
			// t1 "t2 4, t3 5,"
			while (rs.next()) {
				String tagId = rs.getString("tag_id");
				String relatedTags = rs.getString("related_tags");
				HashMap<String, Float> tagsList = sqlOps
						.parseTagsList(relatedTags);
				int occurs = rs.getInt("occurrence");
				TagInfo tag = new TagInfo(tagId, tagsList, occurs);
				tags.put(tagId, tag);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	public float getTagsRecommendPoints(String userId, String prodId) {
		// get user tags
		// Product product = new Product();
		// sqlOps.existsProd(prodId, product);
		// System.out.println(product.pName.name);
		HashMap<String, Float> userTags = sqlOps.getPrefTags(userId);
		HashMap<String, Float> productTags = sqlOps.getTagsForProduct(prodId);
		return getTagsRecommendPoints(userTags, productTags);

	}

	/**
	 * 
	 * @param userTags
	 *            - map(userTag, points in user prefs)
	 * @param prodTags
	 *            - map(prodTag, points by voting tag-prod association)
	 * @return
	 */
	public float getTagsRecommendPoints(HashMap<String, Float> userTags,
			HashMap<String, Float> prodTags) {
		if (userTags == null || prodTags == null)
			return 0;
		// System.out.println("user: " + userTags);
		// System.out.println("prod: " + prodTags);
		float recommSum = 0;
		// get points for all tags
		for (String prodTag : prodTags.keySet()) {
			float prodTagPoints = prodTags.get(prodTag);
			if (prodTagPoints > 0) {
				// check if exists directly in user tags
				boolean matchUserTag = false;
				for (String userTag : userTags.keySet()) {
					if (prodTag.equals(userTag)) {
						float userTagPoints = userTags.get(prodTag);
						recommSum += prodTagPoints * userTagPoints
								/ tags.get(userTag).occurs;
						// System.out.println("\t" + prodTag + ":" + userTag
						// + ":add to sum: " + prodTagPoints + " * "
						// + userTagPoints + "/"
						// + tags.get(userTag).occurs + " MATCHED");
						matchUserTag = true;
					}
				}
				// check in userTags' semantic fields
				if (!matchUserTag) {
					for (String userTag : userTags.keySet()) {
						TagInfo tagToCheck = tags.get(userTag);
						if (tagToCheck != null) {
							HashMap<String, Float> relatedTags = tagToCheck.relatedTags;
							for (String relatedTag : relatedTags.keySet()) {
								if (relatedTag.equals(prodTag)) {
									float userTagPoints = userTags.get(userTag);
									recommSum += prodTagPoints * userTagPoints
											* relatedTags.get(relatedTag)
											/ tagToCheck.occurs;
									// System.out.println("\t" + prodTag + ":"
									// + userTag + ":add to sum: "
									// + prodTagPoints + " * "
									// + userTagPoints + " * "
									// + relatedTags.get(relatedTag) + "/"
									// + tags.get(userTag).occurs);
									break;
								}
							}
						}
					}
				}
			}
		}
		if (recommSum > 1)
			return 1f;
		return recommSum;
	}

	public HashMap<String, Float> getTagsPrefForTag(String tag) {
		return tags.get(tag).relatedTags;
	}

	public void incTagOccurrence(String tag) {
		tags.get(tag).occurs++;
	}

	public TagInfo getTag(String tag) {
		return tags.get(tag);
	}

	public void saveTagPref(String tag, HashMap<String, Float> relatedTags,
			int occ) {
		tags.put(tag, new TagInfo(tag, relatedTags, occ));
	}

	public void addPointsByTags(ArrayList<Product> prodList, String idClient) {
		for (Product product : prodList) {
			product.pointsTags += getTagsRecommendPoints(idClient,
					product.idProd);
		}
	}

}
